package com.atguigu.gmall.car.service.impl;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.atguigu.gmall.car.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;

import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import java.util.*;
import java.util.stream.Collectors;

/**
 * ClassName: CartServiceImpl
 * Package: com.atguigu.gmall.car.service.impl
 * Description:
 *
 * @Author 刘轩
 * @Create 2023-08-31 11:48
 * @Version 1.0
 */

@Service
public class CartServiceImpl implements CartService {


    @Autowired
    private RedisTemplate redisTemplate;

    @Qualifier("com.atguigu.gmall.product.client.ProductFeignClient")
    @Autowired
    private ProductFeignClient productFeignClient;

    /**
     * /**
     * * 添加购物车
     * * @param skuId
     * * @param skuNum
     * * @param request
     * * @return
     */

  /*
    添加购物车业务逻辑！
    判断当前购物车中是否有该商品：
        true:
            商品数量相加
            商品的skuNum 最大200 skuNum>200 200
            每次添加时都是默认选中
            更新一下商品的修改时间
            展示商品最新价格
        false:
            直接添加商品
            hset key field value;
     */
    @Override
    public void addToCart(Long skuId, Integer skuNum, String userId) {
// 组成购物车的key = user:userId :cart


        String cartKey = getCartKey(userId);
        // 判断当前购物车是否又该商品hget key field；
        CartInfo cartInfoExist = (CartInfo) redisTemplate.opsForHash().get(cartKey, skuId.toString());
        if (cartInfoExist != null) {
            // 有这个商品
            Integer Num = cartInfoExist.getSkuNum() + skuNum > 200 ? 200 : cartInfoExist.getSkuNum() + skuNum;
            cartInfoExist.setSkuNum(Num);
            // 设置为选中
//   if(cartInfoExist.getIsChecked().intValue()==0){
//
//    cartInfoExist.setIsChecked(1);
//   }
            cartInfoExist.setIsChecked(1);
            cartInfoExist.setUpdateTime(new Date());
            cartInfoExist.setSkuPrice(productFeignClient.getSkuPrice(skuId));


        } else {
            // 第一次添加该商品
            cartInfoExist = new CartInfo();
            // 通过商品skuid获取商品基本信息
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            cartInfoExist.setSkuId(skuId);
            cartInfoExist.setSkuNum(skuNum);
            cartInfoExist.setUpdateTime(new Date());
            cartInfoExist.setCartPrice(skuInfo.getPrice());
            cartInfoExist.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            cartInfoExist.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfoExist.setSkuName(skuInfo.getSkuName());
            cartInfoExist.setCreateTime(new Date());
            cartInfoExist.setUpdateTime(new Date());

        }
        // 需要将数据保存到缓存
        redisTemplate.opsForHash().put(cartKey, skuId.toString(), cartInfoExist);

        //  写过期的话：1年 ---> 获取每个用户的购买力度！ userId ---> totalAmount 总金额
        //  1个月：70w 2年 淘宝 40w if()else if() else if(){}else{1个月} --- 工厂模式
    }

    /**
     * 查询用户购物车列表
     * 版本1：分别查询未登录购物车列表，以及登录的购物车列表
     * 版本2：将两个购物车中商品合并
     *
     * @param request
     * @return
     */
    @Override
    public List<CartInfo> cartList(String userId, String userTempId) {
        /*
         * 分析合并购物车的过程：
         * 1. userId + userTempId 必须同时存在
         *     userId 存在， 并且通过临时userTempId 查询数据，临时购物车集合必须粤讴数据，才能合并购物车
         * */

        //  声明一个集合来存储临时购物车
        List<CartInfo> cartInfoNoLoginList = new ArrayList<>();
        // 判断
        if (!StringUtils.isEmpty(userTempId)) {
            //  获取临时购物车key
            String cartKey = getCartKey(userTempId);
            //  获取购物车集合
            cartInfoNoLoginList = redisTemplate.opsForHash().values(cartKey);
        }
        //  如果要是没有登录，则返回并排序.
        if (StringUtils.isEmpty(userId)) {
            if (CollectionUtils.isEmpty(cartInfoNoLoginList)) {
                //  安装修改时间进行排序。
                cartInfoNoLoginList.sort((o1, o2) -> {
                    return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
                });
            }

            return cartInfoNoLoginList;
        }


        //  至少有userId
        //  声明一个集合来存储登录购物车
        List<CartInfo> cartInfoLoginList = new ArrayList<>();
        //  获取登录购物车key
        String cartKey = this.getCartKey(userId);
        //  boundHashOps() 也可以操作 opsForHash()
        //  BoundHashOperations<H, HK, HV> hset key field value
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        //cartInfoLoginList = redisTemplate.opsForHash().values(cartKey);
        // 有可能发生合并
        if (!CollectionUtils.isEmpty(cartInfoNoLoginList)) {
            // 一定发生了合并 合并购物车的条件，skuid必须要相同
            // 循环遍历未登录的购物车集合
            for (CartInfo cartInfoNoLogin : cartInfoNoLoginList) {
                // 判断登录对象中是否包含未登录的skuid
                if (boundHashOperations.hasKey(cartInfoNoLogin.getSkuId().toString())) {
                    // 说明skuid相同 未登陆的添加到登陆中
                    CartInfo cartInfoLogin = boundHashOperations.get(cartInfoNoLogin.getSkuId().toString());
                    Integer number = cartInfoLogin.getSkuNum() + cartInfoNoLogin.getSkuNum() > 200 ? 200 : cartInfoLogin.getSkuNum() + cartInfoNoLogin.getSkuNum();
                    cartInfoLogin.setSkuNum(number);
                    cartInfoLogin.setUpdateTime(new Date());
                    // 选中问题： 合并选中，还是选中与不选中的都合并
                    // 价格暂时以数据库为准
                    boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(), cartInfoLogin);
                } else {
                    // 说明skuid不相同
                    //  不相同 29
                    //  相当于新增。
                    //  if (cartInfoNoLogin.getIsChecked().intValue()==1){
                    //      cartInfoNoLogin.setUserId(userId);
                    //      cartInfoNoLogin.setCreateTime(new Date());
                    //      cartInfoNoLogin.setUpdateTime(new Date());
                    //      //  选中不选中?
                    //      boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                    //  }
                    cartInfoNoLogin.setUserId(userId);
                    cartInfoNoLogin.setCreateTime(new Date());
                    cartInfoNoLogin.setUpdateTime(new Date());
                    boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(), cartInfoNoLogin);
                }
            }
            //  删除未登录购物车集合数据：
            this.redisTemplate.delete(this.getCartKey(userTempId));

        }
        //  表示既有合并之后，也有没有合并只有登录的业务！
        cartInfoLoginList = boundHashOperations.values();
        if (CollectionUtils.isEmpty(cartInfoLoginList)) {
            //  返回空对象即可
            return new ArrayList<CartInfo>();
        }
        //  查看购物车的时候，需要按照更新时间进行排序.
        cartInfoLoginList.sort((cart1, cart2) -> DateUtil.truncatedCompareTo(cart2.getUpdateTime(), cart1.getUpdateTime(), Calendar.SECOND));
        //  返回登录数据
        return cartInfoLoginList;
    }
    /**
     * 获取购物车的key
     *
     * @param userId
     * @return
     */
    private String getCartKey(String userId) {
        return RedisConst.USER_LOGIN_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }

    /**
     * 修改选中状态
     * @param skuId
     * @param isChecked
     * @param request
     * @return
     */
    @Override
    public void checkCart(Long skuId, Integer isChecked, String userId) {
        //  获取到修改对象 hget key field;
        String cartKey = this.getCartKey(userId);
        //  获取数据
        CartInfo cartInfo = (CartInfo) this.redisTemplate.opsForHash().get(cartKey,skuId.toString());
        if (null != cartInfo){
            //  赋值选中状态
            cartInfo.setIsChecked(isChecked);
//            cartInfo.setUpdateTime(new Date());
        }
        //  写回缓存 hset key field value;
        this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfo);
    }

    /**
     * 全部选中
     * @param isChecked
     * @param request
     * @return
     */
    @Override
    public void allCheckCart(Integer isChecked, String userId) {
        //  获取到购物车的key
        String cartKey = getCartKey(userId);
        //  获取到所有购物车列表. hvals key;
        List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cartKey);
    /*   // 声明一个map集合
        HashMap<String, CartInfo> hashMap = new HashMap<String, CartInfo>();
        // 判断
        if(!CollectionUtils.isEmpty(cartInfoList)){
            // 遍历
            for (CartInfo cartInfo : cartInfoList) {
                cartInfo.setIsChecked(isChecked);
               // redisTemplate.opsForHash().put(cartKey,cartInfo.getSkuId(),cartInfo);
                hashMap.put(cartInfo.getSkuId().toString(),cartInfo);
            }
        }
        redisTemplate.opsForHash().putAll(cartKey,hashMap);*/

        Map<String, CartInfo> map = cartInfoList.stream().map(cartInfo -> {
            cartInfo.setIsChecked(isChecked);
            return cartInfo;
        }).collect(Collectors.toMap(cartInfo -> {
            return cartInfo.getSkuId().toString();
        }, cartInfo -> {
            return cartInfo;
        }));
        this.redisTemplate.opsForHash().putAll(cartKey,map);
    }
    /**
     * 删除
     *
     * @param skuId
     * @param request
     * @return
     */
    @Override
    public void deleteCart(Long skuId, String userId) {
//        //获取用户购物车Key
//        String cartKey = getCartKey(userId);
//        //获取hash操作对象
//        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
//        //删除购物车商品
//        hashOps.delete(skuId.toString());
        this.redisTemplate.opsForHash().delete(this.getCartKey(userId),skuId.toString());
    }
    /**
     * 清空购物车.
     * @return
     */
    @Override
    public void clearCart(String userId) {
        redisTemplate.delete(getCartKey(userId));
    }
/**
 * 查询用户购物车中已勾选的商品列表
 * @param userId
 * @return
 */
    @Override
    public List<CartInfo> getCartCheckedList(String userId) {
        //  获取到购物车key
        String cartKey = this.getCartKey(userId);
        //  根据key要获取到所有的商品，再判断是否选中.
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        //  需要获取到选中的商品
        List<CartInfo> cartInfoCheckedList = cartInfoList.stream().filter(cartInfo -> cartInfo.getIsChecked().intValue()==1).collect(Collectors.toList());
        //  返回选中商品
        return cartInfoCheckedList;
    }
}

